import { Button, Form, Modal, Tree } from "@douyinfe/semi-ui";
import { useCallback, useEffect, useRef, useState } from "react";
import http from "./http";
import { IPostItem, ITreeNode, MenuType } from "./types";
import { TreeNodeData } from "@douyinfe/semi-ui/lib/es/tree";
import ContextMenu from "./components/contextMenu";
import ControllArea from "./components/controllArea";
import {
  CustomIconFile,
  CustomIconFolder,
  CustomIconHtml,
  CustomIconMD,
} from "./icon/icon";
import { useSettingStore, useTreeStore } from "./store";
import { getParentPath } from "./utils";

function TreeComp({
  onSelected,
  selectedKey,
}: {
  onSelected: (k: string) => void;
  selectedKey: string | undefined;
}) {
  const [treeData, setTreeData] = useState<TreeNodeData[]>([]);
  const [expandedKeys, setExpandedKeys] = useState<string[]>(
    selectedKey ? [getParentPath(selectedKey) ?? ""] : []
  );
  const { showHidden, desc, sortType, currentPath, update } = useSettingStore();
  const { updateTree } = useTreeStore();

  const [editState, setEditState] = useState<{
    type?: string;
    node?: ITreeNode;
    formValue?: IPostItem;
    open: boolean;
    modalTitle: string;
  }>({
    formValue: {
      newName: "UntitledFile",
      isDir: false,
    },
    open: false,
    modalTitle: "",
  });
  const [ctxMenuState, setCtxMenuState] = useState<{
    x: number;
    y: number;
    show: boolean;
    node?: ITreeNode;
  }>({
    x: 0,
    y: 0,
    show: false,
  });

  // 节点右键
  const onCtxMenu = (x: number, y: number, node: ITreeNode) => {
    setCtxMenuState({ x, y, show: true, node });
  };

  const handleSideCtxMenu = (e: React.MouseEvent<HTMLDivElement>) => {
    e.preventDefault();
    setCtxMenuState({ x: e.clientX, y: e.clientY, show: true });
  };

  // 加载树
  const loadTree = useCallback(() => {
    http
      .get(
        `/items?sort=${sortType == "creationTime" ? "1" : "2"}&desc=${
          desc ? 1 : 2
        }&showHidden=${showHidden ? 1 : 0}`
      )
      .then((x) => {
        const treeItems = formatTreeNode(
          sortTreeDate(x.data,sortType, desc),
          onCtxMenu
        );
        setTreeData(treeItems);
        updateTree!(x.data);
      });
  }, [desc, showHidden, sortType]);

  useEffect(() => {
    loadTree();
  }, [showHidden, desc, sortType, loadTree]);

  let title = "";

  const handleClickMenu = (menuId: string, node?: ITreeNode) => {
    const item: IPostItem = {
      newName: "",
      isDir: false,
    };
    switch (menuId) {
      case MenuType.NEW_FILE:
        title = "新建文件";
        if (node) {
          item.parentPath = node.isDir ? node.key : getParentPath(node.key);
        }
        break;
      case MenuType.NEW_FOLDER:
        title = "新建文件夹";
        item.isDir = true;
        if (node) {
          item.parentPath = node.isDir ? node.key : getParentPath(node.key);
        }
        break;
      case MenuType.DELETE:
        title = `确定删除${node?.label}吗？`;
        item.isDir = node?.isDir ?? false;
        break;
      case MenuType.RENAME:
        title = "重命名";
        item.isDir = node?.isDir ?? false;
        if (node) {
          item.parentPath = getParentPath(node.key);
          item.oldName = node.label as string;
          item.newName = node.label as string;
        }
        break;
      case MenuType.REFRESH:
        loadTree();
        return;
      default:
        break;
    }
    setEditState({
      type: menuId,
      node: node,
      formValue: item,
      open: true,
      modalTitle: title,
    });
  };
  const handleModalSubmit = (v: Record<string, any>) => {
    const formValue = editState.formValue;
    formValue!.newName = v.newName;
    if (editState.type == MenuType.DELETE) {
      http.delete("/item?path=" + editState.node?.key).then(() => {
        loadTree();
        update!({
          currentPath: "",
        });
      });
    } else {
      http.post("/item", formValue).then((x: any) => {
        loadTree();
        if (x.data) {
          update!({
            currentPath: x.data,
          });
          onSelected(x.data);
        }
      });
    }
    setEditState({ ...editState, open: false });
  };

  const handleSelectNode = (
    selectedKey: string,
    selected: boolean,
    selectedNode: TreeNodeData
  ) => {
    if (onSelected && selected && !selectedNode.children) {
      if (currentPath == selectedNode.key) {
        return false;
      }
      update!({
        currentPath: selectedKey,
      });
      onSelected(selectedKey);
    }
    if (selectedNode) {
      const { key } = selectedNode;

      // 切换节点的展开状态
      if (expandedKeys.includes(key!)) {
        setExpandedKeys(expandedKeys.filter((k) => k !== key));
      } else {
        setExpandedKeys([...expandedKeys, key!]);
      }
    }
  };

  return (
    <div
      onClick={() => setCtxMenuState({ ...ctxMenuState, show: false })}
      className="h-full"
      onContextMenu={handleSideCtxMenu}
      style={{ borderRight: "1px solid #ccc" }}
    >
      <ControllArea onPullSuccess={loadTree} />

      <Tree
        treeData={treeData}
        showLine
        value={selectedKey}
        onSelect={handleSelectNode}
        expandedKeys={expandedKeys}
        onExpand={(expandedKeys) => setExpandedKeys(expandedKeys)}
      />

      {ctxMenuState.show && (
        <ContextMenu
          x={ctxMenuState.x}
          y={ctxMenuState.y}
          focusItem={ctxMenuState.node}
          onClickMenu={handleClickMenu}
        ></ContextMenu>
      )}
      <Modal
        title={editState.modalTitle}
        visible={editState.open}
        onCancel={() => {
          setEditState({ ...editState, open: false });
        }}
        closeOnEsc={true}
        footer={null}
      >
        <PostItemForm
          onSubmit={handleModalSubmit}
          showForm={editState.type != MenuType.DELETE}
          initValue={editState.formValue}
        ></PostItemForm>
      </Modal>
    </div>
  );
}

function PostItemForm({
  onSubmit,
  showForm,
  initValue,
}: {
  onSubmit: (v: Record<string, any>) => void;
  showForm: boolean;
  initValue: IPostItem | undefined;
}) {
  const inputRef = useRef<any>(null);
  useEffect(() => {
    inputRef.current?.focus();
  }, []);
  return (
    <div style={{ paddingBottom: "10px" }}>
      <Form
        initValues={initValue}
        onSubmit={(values) => {
          onSubmit(values);
        }}
      >
        {showForm && (
          <Form.Input
            ref={inputRef}
            field="newName"
            label="输入名称"
          ></Form.Input>
        )}
        <div className="flex w-full justify-center">
          <Button htmlType={"submit"}>确定</Button>
        </div>
      </Form>
    </div>
  );
}

// semiui-tree
function TreeNode(props: {
  node: ITreeNode;
  onCtxMenu: (x: number, y: number, node: ITreeNode) => void;
}) {
  const handleContextMenu = (e: React.MouseEvent<HTMLDivElement>) => {
    e.preventDefault();
    if (props.onCtxMenu) {
      props.onCtxMenu(e.clientX, e.clientY, props.node);
    }
    e.stopPropagation();
  };
  return (
    <div className="pl-1 w-10/12" onContextMenu={handleContextMenu}>
      {props.node.label}
    </div>
  );
}
// 排序
function sortTreeDate(
  datas: ITreeNode[],
  sortType: "creationTime" | "modTime" | "name" | undefined,
  desc: boolean | undefined
): ITreeNode[] {
  let tmp = [...datas];
  switch (sortType) {
    case "creationTime":
      tmp = tmp.sort((a, b) => {
        console.log(a.label,b.label, (new Date(a.createTime).getUTCMilliseconds() - new Date(b.createTime).getUTCMilliseconds() ))
        return desc == true
        // @ts-ignore
          ? new Date(a.createTime) - new Date(b.createTime) : new Date(b.createTime) - new Date(a.createTime);
      });
      break;
    case "modTime":
      tmp = tmp.sort((a, b) => {
        console.log(a.label,b.label, (new Date(a.modTime).getUTCMilliseconds() - new Date(b.modTime).getUTCMilliseconds() ))
        return desc == true
        // @ts-ignore
          ? new Date(a.modTime) - new Date(b.modTime) : new Date(b.modTime) - new Date(a.modTime);
      });
      break;
      
    default:
      tmp = tmp.sort();
      break;
  }
  for (let index = 0; index < tmp.length; index++) {
    const t = tmp[index];
    if (t.children && t.children.length > 0) {
      t.children = sortTreeDate(t.children, sortType, desc);
    }
  }
  // 文件夹在前
  return tmp.sort((a,b)=> {
    if (a.isDir && !b.isDir) {
      return -1
    }
    return 1
  });
}

function formatTreeNode(
  datas: ITreeNode[],
  onCtxMenu: (x: number, y: number, node: ITreeNode) => void
): TreeNodeData[] {
  const result: TreeNodeData[] = [];

  for (let index = 0; index < datas.length; index++) {
    const item = datas[index];
    const n: TreeNodeData = {
      label: <TreeNode node={item} onCtxMenu={onCtxMenu}></TreeNode>,
      icon: item.isDir ? (
        <CustomIconFolder />
      ) : (
        GetFileIcon(item.label as string)
      ),
      key: item.key,
      value: item.key,
    };
    if (item.children) {
      n.children = formatTreeNode(item.children, onCtxMenu);
    }

    result.push(n);
  }
  return result;
}

function GetFileIcon(filename: string): React.ReactNode {
  const ext = filename.substring(filename.lastIndexOf("."));
  switch (ext) {
    case ".html":
      return <CustomIconHtml />;
    case ".md":
      return <CustomIconMD />;
    default:
      return <CustomIconFile />;
  }
}
export default TreeComp;
